package com.smarthome.common.httpwapper;

import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HttpRequester {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(HttpRequester.class);
    private static HttpClientConnectionPoolManager httpClientManager;
    private static ResponseHandler<HttpResponse> responseHandler;
    
    static{
        httpClientManager = HttpClientConnectionPoolManager.getInstance(1200,400);
        
        //http response处理器
        responseHandler=new HttpResponseHandler();
        
        //守护线程，释放过期连接
        ExpiredConnMonitorThread monitor=new ExpiredConnMonitorThread(httpClientManager,true);
        monitor.start();
    }


    /**
     * 发送HTTP或者仅服务端认证HTTPS  GET请求
     * @param requestUrl  GET请求URL
     * @param headersMap  请求头键值对map
     * @return {@link HttpResponse}
     * @throws Exception
     */
    public static HttpResponse sendGet(String requestUrl, Map<String, String> headersMap) throws Exception {
        HttpResponse httpResponse=null;
        HttpGet get=null;
        try{
            CloseableHttpClient httpClient = null;
            if (StringUtils.containsIgnoreCase(requestUrl, "https")) {
                httpClient =httpClientManager.getCommonHttpsClient();
            } else {
                httpClient =httpClientManager.getHttpClient();
            }
            get=HttpMethod.buildGet(requestUrl, headersMap);
            Long startTime=System.currentTimeMillis();
            httpResponse=httpClient.execute(get,responseHandler);
            LOGGER.info("http请求用时["+(System.currentTimeMillis()-startTime)+"ms]");
        }catch(Exception e){
            releaseGetConnection(get);
            throw e;
        }finally{
            releaseGetConnection(get);
        }
        return httpResponse;
    }

    /**
     * 发送双向认证 HTTPS GET请求
     * @param certStoreType  证书库类型
     * @param certStorePath  证书库位置
     * @param certStorePassword 证书库密码
     * @param requestUrl  请求URL
     * @param headersMap  请求头键值对map
     * @return {@link HttpResponse}
     * @throws Exception
     */
    public static HttpResponse sendGet(String certStoreType, String certStorePath, String certStorePassword, String requestUrl, Map<String, String> headersMap) throws Exception {
        HttpResponse httpResponse=null;
        HttpGet get=null;
        try{
            CloseableHttpClient httpClient = null;
            if (StringUtils.containsIgnoreCase(requestUrl, "https")) {
                httpClient = httpClientManager.getStrictHttpsClient(certStoreType, certStorePath, certStorePassword);
            } else {
                httpClient = httpClientManager.getHttpClient();
            }
            get=HttpMethod.buildGet(requestUrl, headersMap);
            Long startTime=System.currentTimeMillis();
            httpResponse=httpClient.execute(get,responseHandler);
            LOGGER.info("http请求用时["+(System.currentTimeMillis()-startTime)+"ms]");
        }catch(Exception e){
            releaseGetConnection(get);
            throw e;
        }finally{
            releaseGetConnection(get);
        }
        return httpResponse;
    }
    
    /**
     * 发送HTTP或者仅服务端认证HTTPS  POST请求
     * @param requestUrl  POST请求URL
     * @param headersMap  请求头键值对map
     * @param content  POST到服务端的内容
     * @return {@link HttpResponse}
     * @throws Exception
     */
    public static HttpResponse sendPost(String requestUrl, Map<String, String> headersMap, String content) throws Exception {
        HttpResponse httpResponse=null;
        HttpPost post=null;
        try{
            CloseableHttpClient httpClient = null;
            if (StringUtils.containsIgnoreCase(requestUrl, "https")) {
                httpClient =  httpClientManager.getCommonHttpsClient();
            } else {
                httpClient = httpClientManager.getHttpClient();
            }
            post=HttpMethod.buildPost(requestUrl, headersMap, content);
            Long startTime=System.currentTimeMillis();
            httpResponse=httpClient.execute(post,responseHandler);
            LOGGER.info("http请求用时["+(System.currentTimeMillis()-startTime)+"ms]");
        }catch(Exception e){
            releasePostConnection(post);
            throw e;
        }finally{
            releasePostConnection(post);
        }
        return httpResponse;
    }

    /**
     * 发送双向认证 HTTPS GET请求
     * @param certStoreType  证书库类型
     * @param certStorePath  证书库位置
     * @param certStorePassword 证书库密码
     * @param requestUrl  请求URL
     * @param headersMap  请求头键值对map
     * @param content  POST到服务端的内容
     * @return {@link HttpResponse}
     * @throws Exception
     */
    public static HttpResponse sendPost(String certStoreType, String certStorePath, String certStorePassword, String requestUrl, Map<String, String> headersMap, String content) throws Exception {
        HttpResponse httpResponse=null;
        HttpPost post=null;
        try{
            CloseableHttpClient httpClient = null;
            if (StringUtils.containsIgnoreCase(requestUrl, "https")) {
                httpClient = httpClientManager.getStrictHttpsClient(certStoreType, certStorePath, certStorePassword);
            } else {
                httpClient = httpClientManager.getHttpClient();
            }
            post=HttpMethod.buildPost(requestUrl, headersMap, content);
            Long startTime=System.currentTimeMillis();
            httpResponse=httpClient.execute(post,responseHandler);
            LOGGER.info("http请求用时["+(System.currentTimeMillis()-startTime)+"ms]");
        }catch(Exception e){
            releasePostConnection(post);
            throw e;
        }finally{
            releasePostConnection(post);
        }
        return httpResponse;
    }
    
    private static void releasePostConnection(HttpPost post){
        if(post!=null){
            post.releaseConnection(); 
        }
    }
    
    private static void releaseGetConnection(HttpGet get){
        if(get!=null){
            get.releaseConnection();                
        }
    }

}
